Skip to content

Carry reward and per-token model_version, log reward/version metrics#562

Merged
jlamypoirier merged 10 commits into
mainfrom
jlp_reward_model_version
Jul 10, 2026
Merged

Carry reward and per-token model_version, log reward/version metrics#562
jlamypoirier merged 10 commits into
mainfrom
jlp_reward_model_version

Conversation

@jlamypoirier

Copy link
Copy Markdown
Collaborator

Claude Sonnet 5, on behalf of @jlamypoirier.

Summary

Extracted from #553, as an independent piece with no dependency on the documents_seen /
weights_ready PRs (#559, #561) — verified by cherry-picking this commit directly onto main
with no involvement of the other two. The "staleness" framing (documents_seen - model_version)
is a usage note for whoever reads the logged metrics; the code here doesn't compute or need
documents_seen itself.

Was briefly combined with the weights_ready broadcast in #557 (now closed) before splitting
into fully independent pieces.

  • Two optional per-token fields added to the RL streaming schema and threaded through the data
    pipeline alongside advantages / old_log_probabilities (reusing
    TokenDataDocument/TokenDataBatch):
    • reward: the raw (un-normalized) reward, a per-rollout scalar broadcast per-token — distinct
      from the group-relative advantage.
    • model_version: the model version each token was generated under (documents-seen units),
      one per token, for staleness diagnostics.
  • Both are optional (absent when the producer does not send them), so the batch/target plumbing
    guards on presence.
  • The shared policy-gradient loss logs mean/max/min of each supplied field when metrics != none
    (GRPO and GSPO).

Paired PipelineRL change (raw-reward forwarding) is in a separate PR against PipelineRL's
fast-llm branch.

Tests

  • tests/data/test_streaming.py (schema round-trip) and tests/layers/test_lm_losses.py
    (metric registration, single-process and distributed): 584 passed / 21 skipped, 23 passed.
  • The per-token model_version consumer and its metric are in place, but the producer
    (tagging tokens with the active version inside vLLM's output path) is a separate,
    cluster-validated follow-up; until it lands, the model_version/staleness metrics simply don't
    populate.

Add two optional per-token fields to the RL streaming schema and thread
them through the data pipeline alongside `advantages` /
`old_log_probabilities` (reusing `TokenDataDocument`/`TokenDataBatch`):
- `reward`: the raw (un-normalized) reward, a per-rollout scalar broadcast
  per-token — distinct from the group-relative `advantage`.
- `model_version`: the model version each token was generated under
  (documents-seen units), one per token, for staleness diagnostics.

Both are optional (absent when the producer does not send them), so the
batch/target plumbing guards on presence.

The shared policy-gradient loss logs mean/max/min of each supplied field
when `metrics != none` (GRPO and GSPO), registered only when the data is
present. Staleness is `documents_seen - model_version`, derivable from the
logged version stats and `documents_seen`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jlamypoirier and others added 9 commits July 10, 2026 07:51
…rim comments

Inline the one-caller `_get_optional_target` into `_register_data_metrics`,
dropping its dead `targets is None` disjunct (`to_kwargs` always sets the key);
build the max/min sentinels once in the first-iteration init block; narrow the
`losses` annotation to `dict`; move `_DATA_METRIC_FIELDS` above `__init__`; drop
two restating/downstream-referencing comments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The reward is averaged over the sample-filtered training batch, so its mean is
biased and not a valid policy-performance metric. Rename only the logged metric
label (the data field and kwargs key stay `reward`), and note the caveat.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ersion

Staleness must be computed per-step (model-version metrics are summed across
steps and averaged only at log time, so it can't be derived from a single
documents_seen afterwards). Thread the step's documents_seen into the loss
kwargs through the same channel iteration uses (run_step -> BatchContext ->
extra_kwargs), and subtract it from the per-token model version so the loss
logs staleness directly. Other run_step callers take the default 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the file's established name for mask/labeled-token-count weight, and
align the loop variable with the tuple's `data_key` comment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Registering them conditionally on per-batch data presence made the metric's
cross-DP all-reduce data-dependent: with metrics on (pipeline_parallel forced
to 1), a rank that registered the metric all-reduces while a rank that skipped
it does not, so mixed presence across DP ranks would hang. reward/model_version
are always sent when these metrics are enabled, so register unconditionally like
the other policy metrics; absence now fails uniformly instead of hanging. Hoist
the shared per-document weight and extrema sentinels out of the loop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compute staleness (documents_seen - model_version) in the integer domain before
casting to float, so the small difference isn't lost to float32 rounding when
both counts exceed ~2^24. Also spell out neg/pos infinity sentinels, and drop
a code-restating comment and a downstream-consumer reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jlamypoirier jlamypoirier merged commit 4be0ead into main Jul 10, 2026
2 checks passed
@jlamypoirier jlamypoirier deleted the jlp_reward_model_version branch July 10, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant